<?php
namespace App\Supports\Delivery;

use Exception;
use Carbon\Carbon;
use App\Models\Order;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class Express
{
	protected $guzzleOptions;
	
	protected $uri = 'http://poll.kuaidi100.com/poll/query.do';
	
	protected $key;
	protected $customer;
	
	/**
	 * @var Order
	 */
	protected $order;
	
	public function __construct()
	{
		$this->key = config('services.express.key');
		$this->customer = config('services.express.customer');
	}
	
	protected function getGuzzleClient()
	{
		return new Client(['Content-Type' => 'application/x-www-form-urlencoded']);
	}
	
	protected function getParam()
	{
		$params = [
			'com' => $this->order->deliveryCompany(),
			'num' => $this->order->deliveryNumber(),
			'phone' => $this->order->address['contact_phone'],
			'from' => '',
			'to' => '',
			'resultv2' => '1',
		];
		return json_encode($params);
	}
	
	protected function getSign()
	{
		$sign = md5($this->getParam().$this->key.$this->customer);
		return strtoupper($sign);
	}
	
	protected function getPostParams()
	{
		return [
			'customer' => $this->customer,
			'sign' => $this->getSign(),
			'param' => $this->getParam(),
		];
	}
	
	protected function getExpress100FromLocal()
	{
		$savedExpress = [];
		if (isset($this->order->delivery_data['express100'])) {
			$savedExpress = $this->order->delivery_data['express100'];
		}
		return $savedExpress;
	}
	
	protected function isExpress100Expired()
	{
		$express100 = $this->getExpress100FromLocal();
		
		if (!isset($express100['expired_at'])) {
			return true;
		}
		
		$expiredAt = $express100['expired_at'];
		$expiredTime = time_to_carbon($expiredAt);
		return Carbon::now()->gt($expiredTime);
	}
	
	protected function getExpress100FromRemote()
	{
		$response = [];
		
		try {
			$result = $this->getGuzzleClient()
				->post($this->uri, ['query' => $this->getPostParams()])->getBody()->getContents();
			
			$response = json_decode($result, true);
			
			if (isset($response['result']) and $response['result'] === false) {
				return $response;
			}
			
			$response['ischeck_'] = $response['ischeck'] ? '已签收' : '未签收';
			$response['state_'] = config("express.states.{$response['state']}");
			$response['expired_at'] = Carbon::now()->addMinutes(30)->toDateTimeString();
		} catch (Exception $exception) {
			Log::alert('获取快递公司数据异常');
			//var_dump($response);
			return $response;
		}
		
		return $response;
	}
	
	protected function storeExpress100ToLocal(array $express100)
	{
		if (!empty($express100)) {
			DB::transaction(function () use ($express100) {
				$deliveryData = $this->order->delivery_data;
				$deliveryData['express100'] = $express100;
				$deliveryData['express100_last_at'] = Carbon::now();
				$this->order->update(['delivery_data' => $deliveryData]);
				$this->order->items()->update(['delivery_data' => $deliveryData]);
			});
		}
	}
	
	protected function getExpress100($force = false)
	{
		if ($force) {
			// Force get express100 from remote.
			$express100 = $this->getExpress100FromRemote();
			$this->storeExpress100ToLocal($express100);
		} else {
			// Get express100 from local.
			$express100 = $this->getExpress100FromLocal();
			
			// It does not exist then get from remote.
			if (empty($express100) or $this->isExpress100Expired()) {
				$express100 = $this->getExpress100FromRemote();
				$this->storeExpress100ToLocal($express100);
			}
		}
		return $express100;
	}
	
	public function track(Order $order, $force = false)
	{
		$this->order = $order;
		if ($order->delivery_status === 'pending') {
			return [];
		}
		$res= $this->getExpress100($force);


		
		if($res['message']=='ok'){
			$res['company'] = config('express.companies')[$res['com']] ?? '';
			$firstData = [
					"time"=>(string)$order->created_at,
					"ftime"=>(string)$order->created_at,
					"context"=> "快递公司：".$res['company']." 快递单号：".$res['nu']
			];

			array_unshift($res['data'],$firstData);

		}

		return $res;
	}
}
